

#include <string.h>
#include "em_bt_internal.h"
#include "em_bt_def.h"

#include "fr508x.h"
#include "fr508x_at.h"



// 用于提供urc临时解码变量暂存
static at_urc_decode_t  urc_decode;

bool fr508x_on_mac_receive(at_client_t* at, uint8_t* data, uint16_t size)
{
    uint8_t mac[12];
    if( size == 19 && memcmp(data, "+MAC:", 5) == 0 )
    {
        memcpy( mac, data + 5, 12 );
        at_response_t response;
        response.code = at->cmd->type;
        response.pcontext = mac;
        response.result = RET_OK;
        
        at->command_evt_handle( &response );

        return true; 
    }
    return false; 
}
bool fr508x_on_version_receive(at_client_t* at, uint8_t* data, uint16_t size)
{
    uint8_t ver[4];
    if( memcmp(data, "+VER:", 5) == 0)
    {
        at_response_t response;
        response.code = at->cmd->type;
        response.pcontext = ver;

        if( at_client_resp_parse( (char*)data + 5, "%hhu.%hhu.%hhu.%hhu", &ver[3], &ver[2], &ver[1], &ver[0]) == 4)
        {            
            response.result = RET_OK;            
        }
        else 
        {
            response.result = RET_ERROR;
        }
        at->command_evt_handle( &response );
        
        return true; 
    }
    return false; 
}

bool fr508x_on_query_bt_state(at_client_t* at, uint8_t* data, uint16_t size)
{
    if( memcmp(data, "+STATE:", 7) == 0)
    {
        uint8_t state = 0;
        at_response_t response;
        response.code = at->cmd->type;
        response.pcontext = &state; 

        if( at_client_resp_parse((char*)data + 7, "%hhu", &state) == 1)
        {
            response.result = RET_OK;
        }
        else 
        {
            response.result = RET_ERROR; 
        }

        at->command_evt_handle( &response );
        return true; 
    }

    return false; 
}
bool fr508x_on_query_bt_last(at_client_t* at, uint8_t* data, uint16_t size)
{
    uint8_t mac[12];
    at_response_t response;

    if( size == 20 &&  memcmp( data, "+PAIR:", 6) == 0)
    {
        // 保存匹配设备地址
        memcpy( mac, data + 6, 12 );
        
        response.code = at->cmd->type;
        response.pcontext = mac;
        response.result = RET_OK;

        at->command_evt_handle( &response );

        return true; 
    }
    else if( memcmp( data, "FAIL\r\n", 6) == 0 )
    {
        response.code = at->cmd->type;
        response.result = RET_FAIL;
        
        at->command_evt_handle( &response );

        return true; 
    }

    return false; 
}
// bool fr508x_on_query_all_volume(at_client_t* at, uint8_t* data, uint16_t size)
// {
//     return false; 
// }

bool fr508x_on_query_int_source(at_client_t* at, uint8_t* data, uint16_t size)
{
    if( memcmp(data, "+INT:", 5) == 0 )
    {
        uint32_t src = 0;
        at_response_t response;
        response.code = at->cmd->type;
        response.pcontext = &src;
        if( at_client_resp_parse( (char*)data + 5, "%x", &src) == 1)
        {
            response.result = RET_OK;
        }
        else 
        {
            response.result = RET_FAIL;
        }
        at->command_evt_handle( &response );
        return true;
    }
    return false; 
}


bool fr508x_on_int_query_voice_channel(at_client_t* at, uint8_t* data, uint16_t size)
{
    if( memcmp(data, "+VCC:", 5) == 0 )
    {
        uint8_t conn;
        at_response_t response;
        response.code = at->cmd->type;
        response.pcontext = &conn;        
        if( at_client_resp_parse((char*)data + 5, "%hhu", &conn) == 1)
        {
            response.result = RET_OK;
        }
        else 
        {
            response.result = RET_FAIL;
        }
        at->command_evt_handle( &response );

        return true; 
    }
    return true;
}

bool fr508x_on_int_query_media_channel(at_client_t* at, uint8_t* data, uint16_t size)
{
    if( memcmp(data, "+MDC:", 5) == 0 )
    {
        uint8_t conn;
        at_response_t response;
        response.code = at->cmd->type;
        response.pcontext = &conn;        
        if( at_client_resp_parse((char*)data + 5, "%hhu", &conn) == 1)
        {
            response.result = RET_OK;
        }
        else 
        {
            response.result = RET_FAIL;
        }
        at->command_evt_handle( &response );

        return true; 
    }
    return true;
}
bool fr508x_on_int_query_all_volume(at_client_t* at, uint8_t* data, uint16_t size)
{
    if( memcmp(data, "+VOLL:", 6) == 0 ) // volume list 
    {
        fr508x_all_volume_t allvolume;
        int a2dp, hf;
        at_response_t response;
        response.code = at->cmd->type;
    
        if( at_client_resp_parse((char*)data + 6, "%x,%x", &a2dp, &hf) == 2)
        {
            response.result = RET_OK;
        }
        else 
        {
            response.result = RET_FAIL;
        }        
        allvolume.a2dp = a2dp;
        allvolume.hf = hf;
        response.pcontext = &allvolume;

        at->command_evt_handle( &response );

        return true; 
    }

    return true;
}
bool fr508x_on_int_query_disc_reason(at_client_t* at, uint8_t* data, uint16_t size)
{
    if( memcmp( data, "+DISR:", 6) == 0 )
    {
        int disc_reason; 
        at_response_t response;
        response.code = at->cmd->type;

        if( at_client_resp_parse( (char*)data + 6, "%x", &disc_reason) == 1)
        {
            response.result = RET_OK;
        }
        else 
        {
            response.result = RET_FAIL;
        }
        response.pcontext = &disc_reason;

        at->command_evt_handle( &response );
    }
    return true; 
}
// bool fr508x_on_int_query_music_name(at_client_t* at, uint8_t* data, uint16_t size)
// {
//     return true; 
// }

/* AT命令列表
命令列表必须严格按照 no来排序，如果排序是不是+1递增，则寻找AT命令需要增加判断 no序号
*/
ATC_CMD_ARRAY( CMD_LIST_FR508x ) = 
{
    /*          number,             name, e xpr_args,   timeout, retrycnt, ack type,            handle */
    ATC_CMD_DEF( FR_AT_BASE,        NULL,   NULL,       0,      0, AT_CLIENT_ACK_TYPE_NONE,     NULL ), // dummy AT command 
    ATC_CMD_DEF( FR_AT_TEST,        "AT\r\n",   NULL,       200,      3, AT_CLIENT_ACK_TYPE_OK_ERROR,     NULL ), // dummy AT command 
    
    // 电话相关
    ATC_CMD_DEF( FR_AT_CALL_ANSWER,   "AT#CA\r\n",  NULL,   1000,   1, AT_CLIENT_ACK_TYPE_OK_ERROR, NULL ),
    ATC_CMD_DEF( FR_AT_CALL_REJECT,   "AT#CB\r\n",  NULL,   1000,   1, AT_CLIENT_ACK_TYPE_OK_ERROR, NULL ),
    ATC_CMD_DEF( FR_AT_CALL_RECALL,   "AT#CC\r\n",  NULL,   1000,   1, AT_CLIENT_ACK_TYPE_OK_ERROR, NULL ),
    ATC_CMD_DEF( FR_AT_CALL_DIAL,   "AT#CN",  "%s\r\n",   2000,   5, AT_CLIENT_ACK_TYPE_OK_ERROR, NULL ),
    
};

#define cmd_list_count  sizeof(CMD_LIST_FR508x)/sizeof(CMD_LIST_FR508x[0])

const at_client_cmd_t* find_at_by(uint16_t type)
{
    for(int i = 0; i < cmd_list_count; i++)
    {
        if( CMD_LIST_FR508x[i].type == type )
        {
            return &CMD_LIST_FR508x[i];
        }
    }
    return NULL;
}

static bool at_urc_on_event_update(at_client_t* at, uint8_t* data, uint16_t size)
{
    at_response_t response;
    response.code = at->urc->type;
    response.result = RET_OK;
    
    at->urc_evt_handle( &response );//调用 fr508x_at_urc_result zhao
    
    return true;    
}


/*
format:
    +INQ:<mac>,<rssi>,<len>\r\n
    <name>
    name bytes specify by len 
*/
static bool at_urc_bt_on_scan_update(at_client_t* at, uint8_t* data, uint16_t size)
{
    bool result = true;
    
    if( at->recv.fsm == 0 )
    {
        uint32_t mac_msb, mac_lsb;      
        int8_t rssi ;
        uint8_t len_of_name;
        
        uint8_t prefix_len = strlen( at->urc->prefix );
        if( at_client_resp_parse( (char*)(data + prefix_len), "%08X%04X,%hh,%hhu", &mac_msb, &mac_lsb, &rssi, &len_of_name ) == 4 )
//            at_client_resp_parse( (char*)(data + prefix_len), "%08X%04X,%d,%d", &mac_msb, &mac_lsb, &rssi, &len_of_name ) ;
        {
            urc_decode.scan_result.mac[0] = ((mac_msb >> 24) & 0xff);
            urc_decode.scan_result.mac[1] = ((mac_msb >> 16) & 0xff);
            urc_decode.scan_result.mac[2] = ((mac_msb >> 8) & 0xff);
            urc_decode.scan_result.mac[3] = ((mac_msb >> 0) & 0xff);
            urc_decode.scan_result.mac[4] = ((mac_lsb >> 8) & 0xff);
            urc_decode.scan_result.mac[5] = ((mac_lsb >> 0) & 0xff);
            urc_decode.scan_result.namelen = len_of_name;
            urc_decode.scan_result.rssi = rssi;
            urc_decode.scan_result.nameidx = 0;

            at->recv.cmd_mode = false;
            at->recv.fsm = 1;
            at->recv.datasize = len_of_name; 

            result = false; 
        }
      
    }
    else 
    {
        uint8_t chunk_remain = at->recv.datasize - urc_decode.scan_result.nameidx;
        if( chunk_remain > size ) // 进来的数据量未填满，返回false, 继续接收
        {
            chunk_remain = size;       
            result = false;          
        }
        
        memcpy( urc_decode.scan_result.name + urc_decode.scan_result.nameidx, data, chunk_remain );
        urc_decode.scan_result.nameidx += chunk_remain;

        if( result )
        {
            at_response_t response;
            fr508x_bt_device_t device;

            response.code = at->urc->type;            
            response.pcontext = &device;
            device.rssi = urc_decode.scan_result.rssi;
            device.namelen = urc_decode.scan_result.namelen;
            memcpy( device.mac, urc_decode.scan_result.mac, 6 );            
            memcpy( device.name, urc_decode.scan_result.name, urc_decode.scan_result.namelen );

            at->urc_evt_handle( &response );
        }
    }
    
    return result; 
}

static bool at_urc_bt_on_disconnect(at_client_t* at, uint8_t* data, uint16_t size)
{
    char reason[2];
    at_response_t response;
    fr508x_bt_disconnect_t disc;

    response.code = at->urc->type;
    response.pcontext = (void*)&disc;

    uint8_t prefix_len = strlen( at->urc->prefix );

    if( at_client_resp_parse( (char*)data + prefix_len, "%2s", reason) == 1)
    {
        if( reason[0] == 'L' && reason[1] == 'L') // 连接超时
        {
            disc.reason = BT_DISC_BY_TIMEOUT;
        }
        else if( reason[0] == 'U' && reason[1] == 'T') // 用户断开
        {
            disc.reason = BT_DISC_BY_USER;
        }
        else if( reason[0] == 'L' && reason[1] == 'T') // 本地断开
        {
            disc.reason = BT_DISC_BY_LOCAL;
        }
        else if( reason[0] == 'O' && reason[1] == 'T') // 其他原因
        {
            disc.reason = BT_DISC_BY_OTHERS;
        }
        else 
        {
            disc.reason = BT_DISC_BY_UNKNOWN;
        }

        at->urc_evt_handle( &response );
    }

    
    return true;
}
static bool at_urc_bt_on_accessible_change(at_client_t* at, uint8_t* data, uint16_t size)
{
    char state[2];
    at_response_t response;
    fr508x_bt_accessible_t accessible;

    response.code = at->urc->type;
    response.pcontext = &accessible;

    uint8_t prefix_len = strlen( at->urc->prefix );

    if( at_client_resp_parse( (char*)data + prefix_len, "%2s", state) == 1  )
    {
        if( state[0] == 'I' && state[1] == 'I') // 可发现，可连接
        {
            accessible.state = BT_ACCESSIBLE_DISC_CONN;
        }
        else if( state[0] == 'I' && state[1] == 'J' ) // 可连接状态
        {
            accessible.state = BT_ACCESSIBLE_CONN;
        }
        else if( state[0] == 'I' && state[1] == 'K') // 不可发现，不可连接
        {
            accessible.state = BT_ACCESSIBLE_UNDISC_UNCONN;
        }
        else // 未知原因
        {
            accessible.state = BT_ACCESSIBLE_UNKNOWN;
        }

        at->urc_evt_handle( &response );
    }

    return true; 
}

static bool at_urc_on_incoming_call(at_client_t* at, uint8_t* data, uint16_t size)
{
    at_response_t response;
    response.code = at->urc->type;
    fr508x_incomingcall_t incomingcall;

    uint8_t prefix_len = strlen( at->urc->prefix );
    if( at_client_resp_parse( (char*)data + prefix_len, "%19s", incomingcall.number) == 1)
    {
        response.pcontext = &incomingcall;
        at->urc_evt_handle( &response );
    }

    return true; 
}

static bool at_urc_on_music_changed(at_client_t* at, uint8_t* data, uint16_t size)
{
    at_response_t response;
    response.code = at->urc->type;
    at->urc_evt_handle( &response );

    return true; 
}
static bool at_urc_on_music_name_update(at_client_t* at, uint8_t* data, uint16_t size)
{
    bool result = true;
    at_response_t response;
    response.code = at->urc->type;
    
    if( at->recv.fsm == 0 )
    {
        uint32_t total;
        uint32_t namelen;
        uint8_t prefix_len = strlen( at->urc->prefix );
        if( at_client_resp_parse( (char*)data + prefix_len, "%d,%d", &total, &namelen) == 2)
        {
            result = false;
            at->recv.cmd_mode = false; 
            at->recv.datasize = namelen;
            at->recv.fsm = 1;

            urc_decode.musicupdate.time = total;
            urc_decode.musicupdate.namelen = namelen; 
            urc_decode.musicupdate.offset = 0;
        }
    }
    else 
    {
        uint16_t remain = at->recv.datasize - urc_decode.musicupdate.offset;
        if( remain > size )
        {
            result = false;
            remain = size; 
        }
       
        if( urc_decode.musicupdate.offset < BT_MUSIC_NAME_MAX_LEN )
        {
            uint16_t bytes_can_copy = BT_MUSIC_NAME_MAX_LEN - urc_decode.musicupdate.offset; // 检测名称字符串还有多少空间可以拷贝
            if( remain > bytes_can_copy )
            {
                memcpy( urc_decode.musicupdate.name + urc_decode.musicupdate.offset,  data, bytes_can_copy  );
            }
            else 
            {
                memcpy( urc_decode.musicupdate.name + urc_decode.musicupdate.offset,  data, remain );
            }
        }
        urc_decode.musicupdate.offset += remain;

        if( urc_decode.musicupdate.offset >= urc_decode.musicupdate.namelen )
        {
            fr508x_music_t music;
            music.timetotal = urc_decode.musicupdate.time;
            music.len_of_name = urc_decode.musicupdate.namelen;
            if(music.len_of_name > BT_MUSIC_NAME_MAX_LEN)
                music.len_of_name = BT_MUSIC_NAME_MAX_LEN;
            memcpy( music.name, urc_decode.musicupdate.name, music.len_of_name );            

            response.pcontext = &music;
            response.result = RET_OK;
            at->urc_evt_handle( &response );
            
            at->recv.fsm = 0;
        }        
    }    

    return result;
}
static bool at_urc_on_volume_update(at_client_t* at, uint8_t* data, uint16_t size)
{
    bool result = true;
    fr508x_volume_t volume;
    at_response_t response;
    response.code = at->urc->type;
    response.pcontext = &volume;

    uint8_t prefix_len = strlen(at->urc->prefix);
    if( at_client_resp_parse( (char*)data + prefix_len, "%x", &volume.value ) == 1 )
    {
        at->urc_evt_handle( &response );
    }

    return result;
}
static bool at_urc_on_mp3_number(at_client_t* at, uint8_t* data, uint16_t size)
{
    at_response_t response;
    fr508x_mp3_number_t number;
    response.code = at->urc->type;
    response.pcontext = &number;

    uint8_t prefix_len = strlen( at->urc->prefix );
    if( at_client_resp_parse( (char*)data + prefix_len, "%d", &number.nums ) == 1)
    {
        at->urc_evt_handle( &response );
    }

    return true; 
}
static bool at_urc_on_mp3_detail(at_client_t* at, uint8_t* data, uint16_t size)
{
    return true; 
}
static bool at_urc_on_mp3_brief(at_client_t* at, uint8_t* data, uint16_t size)
{
    return true;
}
static bool at_urc_on_mp3_progress(at_client_t* at, uint8_t* data, uint16_t size)
{
    fr508x_mp3_progress_t progress;
    at_response_t response;

    response.code = at->urc->type;
    response.pcontext = &progress;

    uint8_t prefix_len = strlen( at->urc->prefix );
    if( at_client_resp_parse( (char*)data + prefix_len, "%d", &progress.value) == 1)
    {
        at->urc_evt_handle( &response );
    }

    return true; 
}
static bool at_urc_on_pbap_completed(at_client_t* at, uint8_t* data, uint16_t size)
{    
    at_response_t response;
    int code; 
    response.code = at->urc->type;
    response.pcontext = &code;
    
    uint8_t prefix_len = strlen( at->urc->prefix );
    if( at_client_resp_parse( (char*)data + prefix_len, "%04x", &code) == 1)
    {
        at->urc_evt_handle( &response );
    }

    return true; 
}
static bool at_urc_on_pbap_error(at_client_t* at, uint8_t* data, uint16_t size)
{
    at_response_t response;
    int code; 
    response.code = at->urc->type;
    response.pcontext = &code;
    
    uint8_t prefix_len = strlen( at->urc->prefix );
    if( at_client_resp_parse( (char*)data + prefix_len, "%02x", &code) == 1)
    {
        at->urc_evt_handle( &response );
    }

    return true; 
}

// URC no "\r\n"    收到
const at_urc_t FR508x_URC_TABLE[] = 
{
    // 蓝牙打开
    {FR_URC_BT_OPEN,                    "+PWRON", "\r\n",   at_urc_on_event_update },
    // 蓝牙关闭
    {FR_URC_BT_CLOSE,                   "+PWROFF", "\r\n",  at_urc_on_event_update },
    // 串口关闭
    {FR_URC_UART_CLOSE,                 "+SLEEP", "\r\n",   at_urc_on_event_update },
    // 串口打开
    {FR_URC_UART_OPEN,                  "+READY", "\r\n",   at_urc_on_event_update },

        // 连接超时失败
    {FR_URC_BT_CONN_FAIL,         "+CONNFAIL", "\r\n",     at_urc_on_event_update },
    

    
};

